package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	goredislib "github.com/redis/go-redis/v9"
)

func main() {
	// Create a pool with go-redis (or redigo) which is the pool redisync will
	// use while communicating with Redis. This can also be any pool that
	// implements the `redis.Pool` interface.
	client := goredislib.NewClient(&goredislib.Options{
		Addr:     "192.168.1.2:16379",
		Password: "123456",
	})
	pool := goredis.NewPool(client) // or, pool := redigo.NewPool(...)

	// Create an instance of redisync to be used to obtain a mutual exclusion
	// lock.
	rs := redsync.New(pool)

	var gNum = 3
	var wg sync.WaitGroup
	for i := 0; i < gNum; i++ {
		wg.Add(1)
		go func(wg *sync.WaitGroup, tag int) {
			defer wg.Done()

			// Obtain a new mutex by using the same name for all instances wanting the
			// same lock.
			mutexName := "my-global-mutex"
			mutex := rs.NewMutex(mutexName)

			fmt.Println(tag, " 开始获取锁")
			// Obtain a lock for our given mutex. After this is successful, no one else
			// can obtain the same lock (the same mutex name) until we unlock it.
			if err := mutex.Lock(); err != nil {
				panic(err)
			}
			fmt.Println(tag, " 获取锁成功")

			// Do your work that requires the lock.
			// 模拟耗时任务
			time.Sleep(time.Second)

			// Release the lock so other processes or threads can obtain a lock.
			if ok, err := mutex.Unlock(); !ok || err != nil {
				panic("unlock failed")
			}
			fmt.Println(tag, " 释放锁成功")
		}(&wg, i)
	}

	wg.Wait()
}
